#pragma once

#include <string_view>
#include <memory>

namespace thread {

class ThreadPool : public std::enable_shared_from_this<ThreadPool> {
 public:
  ThreadPool();
  virtual ~ThreadPool();

  virtual void OnMainThreadTick();

  bool HasThread(TPThread *thread);

  std::string PrintState();

  uint32_t GetCurrentThreadCount() const;

  uint32_t GetCurrentFreeThreadCount() const;

  bool CreateThreadPool(uint32_t increase_count, uint32_t keep_count,
                        uint32_t max_count);

  bool AddTask(ThreadTask *task);
  bool AddTaskInternal(ThreadTask *task);

  bool IsBusy() const;

  bool IsEnable() const;

  bool IsDestoryed() const;

  void Destory();

  uint32_t GetBufferedListSize() const;

  std::queue<std::shared_ptr<ThreadTask>> &GetBufferedList();

  uint32_t GetFinishedListSize() const;

  virtual std::string_view GetThreadPoolName() const;

  void Finalise();

  virtual TPThread *CreateThread(int wait_second        = ThreadPool::timeout,
                                 bool start_immediately = true);

  void BufferTask(ThreadTask *task);

  ThreadTask *PopBufferTask();

  bool AddFreeThread(TPThread *thread);

  bool AddBusyThread(TPThread *thread);

  void AddFinishedTask(ThreadTask *task);

  bool RemoveHangThread(TPThread *thread);

 private:
  static int timeout;
  class ThreadPoolImpl;
  std::unique_ptr<ThreadPoolImpl> impl_;
};

}  // namespace thread